import type { RouteRecordRaw } from 'vue-router';

import { useAppStore } from '/@/store/modules/app';
import { usePermissionStore } from '/@/store/modules/permission';
import { useUserStore } from '/@/store/modules/user';

import { useTabs } from './useTabs';

import { router, resetRouter } from '/@/router';
// import { RootRoute } from '/@/router/routes';

import projectSetting from '/@/settings/projectSetting';
import { PermissionModeEnum } from '/@/enums/appEnum';
import { RoleEnum } from '/@/enums/roleEnum';

import { intersection } from 'lodash-es';
import { isArray } from '/@/utils/is';
import { useMultipleTabStore } from '/@/store/modules/multipleTab';

/**
 * 封装与用户权限相关的操作
 * @returns 返回一个对象，包含了与用户权限相关的操作
 */
export function usePermission() {
  const userStore = useUserStore();
  const appStore = useAppStore();
  const permissionStore = usePermissionStore();
  const { closeAll } = useTabs(router);

  /**
   * 切换权限模式的异步函数，在前端权限模式和后端权限模式之间切换
   * @returns 无
   */
  async function togglePermissionMode() {
    appStore.setProjectConfig({
      permissionMode:
        appStore.projectConfig?.permissionMode === PermissionModeEnum.BACK
          ? PermissionModeEnum.ROUTE_MAPPING
          : PermissionModeEnum.BACK,
    });
    //location.reload() 用于重新加载当前页面,这个过程类似于用户点击浏览器的刷新按钮或者使用键盘的刷新快捷键。
    location.reload();
  }

  /**
   * 重置和重新获得权限资源信息
   * @returns 无
   */
  async function resume() {
    const tabStore = useMultipleTabStore(); // 使用 useMultipleTabStore() 方法获取多标签页的状态管理对象
    tabStore.clearCacheTabs(); // 清除缓存标签页
    resetRouter(); // 重置路由器
    const routes = await permissionStore.buildRoutesAction(); // 异步构建权限路由
    routes.forEach((route) => {
      router.addRoute(route as unknown as RouteRecordRaw); // 将构建的权限路由添加到路由器中
    });
    permissionStore.setLastBuildMenuTime(); // 设置最后一次构建菜单的时间
    closeAll(); // 关闭所有标签页
  }

  /**
   * 判断当前用户是否具有指定权限
   * @param value 权限值，可以是单个权限字符串或字符串数组，也可以是 RoleEnum 枚举值或枚举值数组
   * @param def 默认权限值，若未提供 value 参数则返回默认权限值
   * @returns boolean - 是否具有权限
   */
  function hasPermission(value?: RoleEnum | RoleEnum[] | string | string[], def = true): boolean {
    // Visible by default
    if (!value) {
      return def;
    }

    const permMode = projectSetting.permissionMode;

    // 如果权限模式为路由映射模式或角色模式，则判断角色是否有权限
    if ([PermissionModeEnum.ROUTE_MAPPING, PermissionModeEnum.ROLE].includes(permMode)) {
      if (!isArray(value)) {
        return userStore.getRoleList?.includes(value as RoleEnum);
      }
      return (intersection(value, userStore.getRoleList) as RoleEnum[]).length > 0;
    }

    // 如果权限模式为后端权限模式
    if (PermissionModeEnum.BACK === permMode) {
      //取权限代码列表
      const allCodeList = permissionStore.getPermCodeList as string[];
      if (!isArray(value)) {
        // 分隔符数组
        const splits = ['||', '&&'];
        // 找到 value 中包含的分隔符
        const splitName = splits.find((item) => value.includes(item));
        if (splitName) {
          // 根据分隔符将 value 分割成多个权限代码
          const splitCodes = value.split(splitName);
          // 如果分隔符为 '||'，判断 splitCodes 与 allCodeList 的交集是否不为空
          // 如果分隔符为 '&&'，判断 splitCodes 与 allCodeList 的交集长度是否等于 splitCodes 的长度
          return splitName === splits[0]
            ? intersection(splitCodes, allCodeList).length > 0
            : intersection(splitCodes, allCodeList).length === splitCodes.length;
        }
        // 如果 value 中不包含分隔符，则判断 allCodeList 是否包含 value
        return allCodeList.includes(value);
      }
      // 如果 value 是数组，则判断 value 与 allCodeList 的交集是否不为空
      return (intersection(value, allCodeList) as string[]).length > 0;
    }
    return true;
  }

  /**
   * Change roles
   * @param roles
   */
  async function changeRole(roles: RoleEnum | RoleEnum[]): Promise<void> {
    if (projectSetting.permissionMode !== PermissionModeEnum.ROUTE_MAPPING) {
      throw new Error(
        'Please switch PermissionModeEnum to ROUTE_MAPPING mode in the configuration to operate!',
      );
    }

    if (!isArray(roles)) {
      roles = [roles];
    }
    userStore.setRoleList(roles);
    await resume();
  }

  /**
   * refresh menu data
   */
  async function refreshMenu() {
    resume();
  }

  return { changeRole, hasPermission, togglePermissionMode, refreshMenu };
}
